<html>
<head>
    <title>
        Org Chart
    </title>
    <style type="text/css">
        .header {
            color: #77DD33;
            background-color: #DDDDDD;
            font-size: 40px;
            text-align: center;
        }
    </style>
    <link rel="stylesheet" type="text/css" href="http://organizational-chart-gadget.googlecode.com/svn/trunk/huluorgchart.css" /></link>
    <script src="http://www.google.com/jsapi" type="text/javascript"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js" type="text/javascript"></script>
    <script type="text/javascript">

        google.load('visualization', '1', {packages:['orgchart']});
        google.setOnLoadCallback(initialize);
        
        function initialize() {
          var query = new google.visualization.Query('https://spreadsheets.google.com/a/hulu.com/ccc?key=tWHfpY2lNgiC2Ik5-IBOLxQ');
          query.send(responseHandler);
        };

        var employees = $H();
        var managers = $H();
        var teams = $H();

        var Employee = Class.create({
          initialize: function(employeeInfo){
            this.positionID = employeeInfo["positionID"];
            this.name = employeeInfo["name"];
            this.manager = employeeInfo["manager"];
            this.type = employeeInfo["type"];
            this.team = employeeInfo["team"];
            this.title = employeeInfo["title"];
            this.hireDate = employeeInfo["hireDate"];
            this.isManager = false;
            this.members = $A([]);
            this.chartOrder = "0";
            this.chartID = "";
            this.chartDisplay = "";
            this.chartManager = "";
            this.chartTip = this.name;
          },

          generateChartOrder: function(){
            if(this.name == "TBH")
            {
              this.chartOrder = "9"
              return;
            }
            if(this.type == "FTE")
              this.chartOrder = "0";
            else if(this.type == "Intern")
              this.chartOrder = "1";
            else
              this.chartOrder = "2";
          },

          generateChartProperties: function(){
            this.generateChartOrder();
            if(this.name == "TBH")
              this.chartDisplay = "<p class='hulu-orgchart-node-name' type='TBH'>"+this.name+" "+ this.hireDate+"</p><p class='hulu-orgchart-node-title'>"+this.title+"</p></div>";
            else
             this.chartDisplay = "<p class='hulu-orgchart-node-name' type='"+this.type+"'>"+this.name+"</p><p class='hulu-orgchart-node-title'>"+this.title+"</p></div>";
          },

          getMemberNumber: function()
          {
            return 1 + this.members.inject(0, function(acc,id){
              if(managers.get(id)){
                var mem = employees.get(managers.get(id));
                if (mem.members.size())
                  return acc + mem.getMemberNumber();
                else
                  return acc + 0;
              }

              if(teams.get(id))
                return acc + teams.get(id).getMemberNumber();
            });
          }
        });

        var Team = Class.create({
          initialize: function(name,manager){
            this.name = name;
            this.manager = manager;
            this.members = $A([]);
            this.chartID = name + "-" + manager;
            this.chartDisplay = "<p class='hulu-orgchart-node-name' type='Team'>" + this.name + "</p>";
            this.chartManager = null;
            this.chartTip = this.manager;
          },
          getMemberNumber: function()
          {
            return this.members.size();
          }
        });

        Team.generateChartID =  function(name,manager){return name + "-" + manager;};

        function responseHandler(response) {
          if (response.isError())
          {
              alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage()); return; 
          }
          var container = document.getElementById('chart');
          container.style.width = document.body.clientWidth + 'px';
          container.style.height = document.body.clientHeight + 'px';
          var visualizationObject =
              new google.visualization.OrgChart(container);

          var dataTable = response.getDataTable();

          readOrgRable(dataTable);
          sortMembers();

          // add chart infomation
          managers.each(function(manInfo){
            if(!manInfo.value)
              return;
            var manager = employees.get(manInfo.value);

            manager.members.each(function(id){
                if(managers.get(id))
                  return employees.get(managers.get(id)).chartManager = manager.chartID;
                else
                  return teams.get(id).chartManager = manager.chartID;
            });
          });

          teams.each(function(teamInfo){
            var team = teamInfo.value;
            if(!team.members.size())
              return;
            employees.get(team.members[0]).chartManager = team.chartID;
            for (var index = 1, len = team.members.size(); index < len; ++index)
              employees.get(team.members[index]).chartManager = employees.get( team.members[index - 1] ).chartID;
          });

          // create the organizational table
          var chartTable = new google.visualization.DataTable();
          chartTable.addColumn('string', 'Name');
          chartTable.addColumn('string', 'Manager');
          chartTable.addColumn('string', 'ToolTip');

          insertEmployees(chartTable);

          var options = {allowHtml:true, selectedNodeClass:"hulu-orgchart-nodesel"};
          visualizationObject.draw(chartTable, options);

          resetChartStyle();
        };

        // read the organizational table, and generate corresponding objects
        function readOrgRable(dataTable)
        {
          // create all the employee objects
          for (var row = 1,rowCount = dataTable.getNumberOfRows(); row < rowCount; ++row)
          {
            var employeeInfo = {};

            for (var column = 0,columnCount = dataTable.getNumberOfColumns(); column < columnCount; ++column) {
              var label = dataTable.getFormattedValue(0,column);
                //if (column == 6)
                //label = "Hire Date"
              switch (label)
              {
                case "Position ID":
                  employeeInfo["positionID"] = dataTable.getFormattedValue(row, column);
                  break;
                case "Employee Name":
                  employeeInfo["name"] = dataTable.getFormattedValue(row, column);
                  if(employeeInfo["name"] == "TBH")
                    var t = "Hello";
                  break;
                case "Manager":
                  if(!dataTable.getFormattedValue(row, column))
                    employeeInfo["manager"] = "root";
                  else
                    employeeInfo["manager"] = dataTable.getFormattedValue(row, column);
                  break;
                case "Type":
                  employeeInfo["type"] = dataTable.getFormattedValue(row, column);
                  break;
                case "Team":
                  if(!dataTable.getFormattedValue(row, column))
                    employeeInfo["team"] = "Others"
                  else
                    employeeInfo["team"] = dataTable.getFormattedValue(row, column);
                  break;
                case "Title":
                  employeeInfo["title"] = dataTable.getFormattedValue(row, column);
                  break;
                case "Hire Date":
                  employeeInfo["hireDate"] = dataTable.getFormattedValue(row, column);
                  break;
              }
            }

            var employee = new Employee(employeeInfo);
            employee.chartID = row + "-" + employee.name;
            employee.generateChartProperties();

            if( !managers.keys().include(employee.manager) )
              managers.set(employee.manager, null);

            var teamID = Team.generateChartID(employee.team, employee.manager);
            if( !teams.keys().include(teamID) )
            {
              var team = new Team( employee.team, employee.manager )
              teams.set(team.chartID, team);
            }
            employees.set(employee.chartID, employee);
          }

          employees.each(function(emInfo){
            var em = emInfo.value;
            if( managers.keys().include(em.name) )
            {
              managers.set(em.name, em.chartID);
              em.isManager = true;
            }
            else
            {
              var teamID = Team.generateChartID(em.team,em.manager);
              teams.get(teamID).members.push(em.chartID);
            }
          });

          employees.each(function(emInfo){
            var em = emInfo.value;
            if( !managers.get(em.manager) )
              return;

            var manager = employees.get(managers.get(em.manager));
            if( em.isManager )
            {
              manager.members.push(em.name);
            }
            else
            {
              var teamID = Team.generateChartID(em.team,em.manager);
              if ( !manager.members.include(teamID) )
              {
                manager.members.push(teamID);
              }
            }
          });
        }

        function sortMembers()
        {
          managers.each(function(manInfo){
            if(!manInfo.value)
              return;
            var manager = employees.get(manInfo.value);

            manager.members = manager.members.sortBy(function(memName){
                if(managers.get(memName))
                  return employees.get(managers.get(memName)).getMemberNumber();
                else
                  return teams.get(memName).getMemberNumber();
            }).reverse();

          });

          teams.each(function(teamInfo){
            var team = teamInfo.value;
            if(team.members.size())
              team.members = team.members.sortBy(function(id){return employees.get(id).chartOrder+employees.get(id).type + employees.get(id).name});
          });
        }

        function insertEmployees(chartTable)
        {
          managers.each(function(manInfo){
            insertManager(chartTable, manInfo.key);
          });
        }

        function insertManager(chartTable, manKey)
        {
          if(!managers.get(manKey))
              return;
          var manager = employees.get(managers.get(manKey));

          var index = chartTable.addRow([{v:manager.chartID, f:manager.chartDisplay}, manager.chartManager, "" ]);
          chartTable.setRowProperty(index,"id","FTE")
          managers.unset(manKey);

          if( manager.members.size() )
          {
            for (var index = 0, len = manager.members.length; index < len; ++index)
            {
              var memID = manager.members[index];
              if(managers.get(memID))
              {
                insertManager(chartTable, memID);
              }
              if( teams.get(memID) )
              {
                insertTeam(chartTable, memID);
              }
            }
          }
        }

        function insertTeam(chartTable, teamKey)
        {
          var team = teams.get(teamKey);
          chartTable.addRow([ {v:team.chartID,f:team.chartDisplay}, team.chartManager, "" ]);
          team.members.each(function(id){
            var em = employees.get(id);
            chartTable.addRow( [ {v:em.chartID, f:em.chartDisplay}, em.chartManager, em.chartTip ] );
          });
        }

        function resetChartStyle()
        {
          var classes = $w("orgchart-table orgchart-space-small orgchart-space-medium orgchart-space-large orgchart-noderow-small orgchart-noderow-medium orgchart-noderow-large orgchart-connrow-small orgchart-connrow-medium orgchart-connrow-large orgchart-node orgchart-nodesel orgchart-node-small orgchart-node-medium orgchart-node-large orgchart-linenode orgchart-lineleft orgchart-lineright orgchart-linebottom");
          classes.each(function(className){
            $$(".google-visualization-"+className).each(function(el){
              el.removeClassName("google-visualization-"+className);
              el.addClassName("hulu-"+className);
            });
          });

          $$(".hulu-orgchart-node-name").each(function(el){
            var tdParent = el.up("td");
            tdParent.addClassName("hulu-orgchart-node-"+el.getAttribute("type"));
          });
        }
    </script>
</head>

<body>
<div class="header">Org Chart</div>
<div id="chart" style="align: center; width: 700px; height: 300px;"></div>
</body>
</html>